use build_builder::Builder;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};

use crate::logistics::{Cargo, Receiver, Sender, Shop, UseInsured};

#[derive(Clone, Debug, Serialize)]
pub struct ImmeDeliveryReq {}

#[derive(Clone, Debug, Deserialize)]
pub struct ImmeDeliveryRes {
    pub resultcode: u32,
    pub resultmsg: String,
    pub list: Vec<ImmeDeliver>,
}

#[derive(Clone, Debug, Deserialize)]
pub struct ImmeDeliver {
    pub delivery_id: String,
    pub delivery_name: String,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct PreAddOrderReq {
    shopid: String,
    shop_order_id: String,
    delivery_id: String,
    openid: String,
    sender: Sender,
    receiver: Receiver,
    cargo: Cargo,
    order_info: OrderInfo,
    shop: Shop,
    delivery_sign: String,
    shop_no: String,
    sub_biz_id: String,
    order_source: Option<String>,
    order_sequence: Option<String>,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct OrderInfo {
    delivery_service_code: Option<String>,
    expected_delivery_time: Option<u32>,
    order_type: Option<u32>,
    poi_deq: Option<String>,
    note: Option<String>,
    order_time: u32,
    is_insured: Option<UseInsured>,
    declared_value: Option<u32>,
    tips: Option<u32>,
    is_direct_delivery: Option<u32>,
    cash_on_delivery: Option<u32>,
    cash_on_pickup: Option<u32>,
    rider_pick_method: Option<u32>,
    is_finish_code_needed: Option<u32>,
    is_pickup_code_needed: Option<u32>,
    expected_finish_time: Option<u32>,
    expected_pick_time: Option<u32>,
}

#[derive(Clone, Debug, Deserialize)]
pub struct PreAddOrderRes {}

#[derive(Clone, Debug, Serialize)]
pub struct BindAccountReq;

#[derive(Clone, Debug, Deserialize)]
pub struct BindAccountRes {
    pub resultcode: u32,
    pub resultmsg: String,
    pub shop_list: Vec<ShopItem>,
}

#[derive(Clone, Debug, Deserialize)]
pub struct ShopItem {
    pub shopid: String,
    pub delivery_id: String,
    pub audit_result: AuditStatus,
}

#[derive(Clone, Debug, Deserialize_repr)]
#[repr(u8)]
pub enum AuditStatus {
    Allow = 0,
    Auditing = 1,
    Disallow = 2,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct PreCancelOrderReq {
    shopid: String,
    shop_order_id: String,
    delivery_id: String,
    waybill_id: String,
    cancel_reason_id: Option<String>,
    cancel_reason: Option<String>,
    shop_no: String,
    delivery_sign: String,
}

#[derive(Clone, Debug, Deserialize, Builder)]
pub struct PreCancelOrderRes {
    pub resultcdoe: u32,
    pub resultmsg: String,
    pub deduct_fee: u32,
    pub desc: String,
}

#[derive(Clone, Debug, Serialize)]
pub struct OpenDeliveryReq {}

#[derive(Clone, Debug, Deserialize)]
pub struct OpenDeliveryRes {
    pub resultcode: u32,
    pub resultmsg: String,
}

#[derive(Clone, Debug, Serialize)]
pub struct BindLocalAccountReq {
    delivery_id: String,
}

impl BindLocalAccountReq {
    pub fn new<T>(id: T) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            delivery_id: id.as_ref().to_owned(),
        }
    }
}

#[derive(Clone, Debug, Deserialize)]
pub struct BindLocalAccountRes {
    pub resultcode: u32,
    pub resultmsg: String,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct ReOrderReq {
    shopid: String,
    shop_order_id: String,
    delivery_id: String,
    openid: String,
    sender: Sender,
    receiver: Receiver,
    cargo: Cargo,
    order_info: OrderInfo,
    shop: Shop,
    delivery_token: String,
    delivery_sign: String,
    shop_no: String,
    sub_biz_id: Option<String>,
    order_source: Option<String>,
    order_sequence: Option<String>,
}

#[derive(Clone, Debug, Deserialize)]
pub struct ReOrderRes {
    pub resultcode: u32,
    pub resultmsg: String,
    pub fee: u32,
    pub deliverfee: u32,
    pub couponfee: u32,
    pub tips: u32,
    pub insurancfee: u32,
    pub distance: u32,
    pub waybill_id: String,
    pub order_status: u32,
    pub finish_code: u32,
    pub pickup_code: u32,
    pub dispatch_duration: u32,
}
#[derive(Clone, Debug, Serialize)]
pub struct RealMockUpdateOrderReq {
    shopid: String,
    shop_order_id: String,
    order_status: u32,
    action_time: u32,
    action_msg: Option<String>,
    delivery_sign: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct RealMockUpdateOrderRes {
    pub resultcode: u32,
    pub resultmsg: String,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct MockUpdateOrderReq {
    shopid: String,
    shop_order_id: String,
    order_status: u32,
    action_time: u32,
    action_msg: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct MockUpdateOrderRes {
    pub resultcode: u32,
    pub resultmsg: String,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct GetLocalOrderReq {
    shopid: String,
    shop_order_id: String,
    shop_no: String,
    delivery_sign: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct GetLocalOrderRes {
    pub resultcode: u32,
    pub resultmsg: String,
    pub order_status: u32,
    pub waybill_id: String,
    pub rider_name: String,
    pub rider_phone: String,
    pub rider_lng: u32,
    pub rider_lat: u32,
    pub reach_time: u32,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct AbnormalConfirmReq {
    shopid: String,
    shop_order_id: String,
    waybill_id: String,
    delivery_sign: String,
    shop_no: String,
    remark: Option<String>,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct CancelLocalOrderReq {
    shopid: String,
    shop_order_id: String,
    delivery_id: String,
    waybill_id: Option<String>,
    cancel_reason_id: u32,
    cancel_reason: String,
    shop_no: String,
    delivery_sign: String,
}

#[derive(Clone, Debug, Deserialize)]
pub struct CancelLocalOrderRes {
    pub deduce_fee: u32,
    pub desc: String,
    pub resultcode: u32,
    pub resultmsg: String,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct AddTipsReq {
    shopid: String,
    shop_order_id: String,
    waybill_id: String,
    tips: u32,
    remark: String,
    delivery_sign: String,
    shop_no: String,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct AddLocalOrderReq {
    shopid: String,
    shop_order_id: String,
    delivery_id: String,
    openid: String,
    sender: Sender,
    receiver: Receiver,
    cargo: Cargo,
    order_info: OrderInfo,
    shop: Shop,
    delivery_token: String,
    delivery_sign: String,
    shop_no: String,
    sub_biz_id: Option<String>,
    order_source: Option<String>,
    order_sequence: Option<String>,
}

#[derive(Clone, Debug, Deserialize)]
pub struct AddLocalOrderRes {
    pub resultcode: u32,
    pub resultmsg: String,
    pub fee: u32,
    pub deliverfee: u32,
    pub couponfee: u32,
    pub tips: u32,
    pub insurancfee: u32,
    pub distance: u32,
    pub waybill_id: String,
    pub order_status: u32,
    pub finish_code: u32,
    pub pickup_code: u32,
    pub dispatch_duration: u32,
}
#[derive(Clone, Debug, Serialize, Builder)]
pub struct UpdateOrderReq {
    wx_token: String,
    order_status: u32,
    waybill_id: String,
    action_msg: Option<String>,
    action_time: u32,
    agent: Agent,
    shopid: String,
    shop_order_id: String,
    shop_no: Option<String>,
    wxa_path: String,
    expected_delivery_time: Option<u32>,
}

#[derive(Clone, Debug, Serialize, Builder)]
pub struct Agent {
    name: String,
    phone: String,
    is_phone_encrypted: PhoneEncrypted,
}

#[derive(Clone, Debug, Serialize_repr)]
#[repr(u8)]
pub enum PhoneEncrypted {
    No = 0,
    Yes = 1,
}
